package tcpServer

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net"
	"runtime/debug"
	"sync"
	"time"

	"github.com/RuiGuangServer/config"
	"github.com/RuiGuangServer/protocol"
	"github.com/RuiGuangServer/utils"

	"google.golang.org/protobuf/proto"
)

// Client 客户端结构体
type Client struct {
	conn         net.Conn
	server       *TCPServer
	lastActive   time.Time
	airportNum   string
	uuid         string
	isValidUUID  bool
	isRegistered bool
	writeChan    chan []byte
	closeChan    chan struct{}
	closeOnce    sync.Once
	readBuffer   []byte    // 预分配的读取缓冲区
	bufferPool   sync.Pool // 对象池，减少内存分配
}

// NewClient 创建客户端实例
func NewClient(conn net.Conn, server *TCPServer) *Client {
	c := &Client{
		conn:       conn,
		server:     server,
		lastActive: time.Now(),
		writeChan:  make(chan []byte, 10),
		closeChan:  make(chan struct{}),
		readBuffer: make([]byte, 4096), // 预分配4KB缓冲区
	}
	c.bufferPool.New = func() any {
		buf := make([]byte, 4096)
		return &buf // 返回指针而不是切片
	}
	return c
}

// handleReadError 读取错误记录
func (c *Client) handleReadError(err error) {
	var netErr net.Error
	if err == io.EOF {
		c.server.logger.Info("Client %s disconnected (EOF)", c.conn.RemoteAddr())
	} else if errors.As(err, &netErr) && netErr.Timeout() {
		c.server.logger.Warn("Read timeout from %s", c.conn.RemoteAddr())
	} else if errors.Is(err, io.ErrClosedPipe) || errors.Is(err, net.ErrClosed) {
		c.server.logger.Info("Client %s connection closed", c.conn.RemoteAddr())
	} else if errors.Is(err, io.ErrUnexpectedEOF) {
		c.server.logger.Warn("Client %s unexpected EOF (connection reset)", c.conn.RemoteAddr())
	} else {
		c.server.logger.Error("Read error from %s: %v", c.conn.RemoteAddr(), err)
	}
}

// handleConnection 处理消息连接
func (c *Client) handleConnection() {
	defer func() {
		if r := recover(); r != nil {
			c.server.logger.Error("Connection panic: %v\n%s", r, debug.Stack())
		}
		c.Close()
		// 移除这行：c.server.wg.Done()
		// 因为我们在服务器层面不再使用WaitGroup跟踪每个客户端
	}()

	readChan := make(chan []byte, 10)
	errChan := make(chan error, 1)
	emptyDataChan := make(chan bool, 1)

	// 启动读写goroutine
	go c.readLoop(readChan, errChan, emptyDataChan)
	go c.writeLoop()

	// 设置连接空闲超时
	idleTimeout := time.Duration(config.Config.Heartbeat*3) * time.Millisecond
	idleTimer := time.NewTimer(idleTimeout)
	defer idleTimer.Stop()

	for {
		select {
		case data := <-readChan:
			if !idleTimer.Stop() {
				<-idleTimer.C
			}
			idleTimer.Reset(idleTimeout)

			if len(data) == 0 {
				c.server.logger.Warn("Client %s sent empty data, closing connection", c.conn.RemoteAddr())
				return
			}

			if err := c.processData(data); err != nil {
				c.server.logger.Error("Process data error: %v", err)
				return
			}

		case <-emptyDataChan:
			c.server.logger.Warn("Client %s sent multiple empty packets, closing connection", c.conn.RemoteAddr())
			return

		case err := <-errChan:
			c.handleReadError(err)
			return

		case <-idleTimer.C:
			if c.isRegistered {
				c.server.logger.Warn("Client %s idle timeout, closing connection", c.conn.RemoteAddr())
			} else {
				c.server.logger.Warn("Unregistered client %s connection timeout, closing", c.conn.RemoteAddr())
			}
			return

		case <-c.closeChan:
			return

		case <-c.server.stopChan:
			return
		}
	}
}

// readLoop 循环读取
func (c *Client) readLoop(readChan chan<- []byte, errChan chan<- error, emptyDataChan chan<- bool) {
	defer close(readChan)
	defer close(errChan)
	defer close(emptyDataChan)

	emptyDataCount := 0         // 空数据计数器
	const maxEmptyDataCount = 3 // 最大允许的空数据次数

	for {
		select {
		case <-c.closeChan:
			return
		default:
			// 获取指针
			bufPtr := c.bufferPool.Get().(*[]byte)
			buf := *bufPtr // 解引用

			// 设置读取超时
			_ = c.conn.SetReadDeadline(time.Now().Add(c.server.readTimeout))
			n, err := c.conn.Read(buf)

			if err != nil {
				c.bufferPool.Put(bufPtr) // 出错时放回指针

				// 处理连接关闭或重置的情况
				if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) ||
					errors.Is(err, io.ErrClosedPipe) || errors.Is(err, io.ErrUnexpectedEOF) {
					errChan <- err
					return
				}

				var netErr net.Error
				if errors.As(err, &netErr) && netErr.Timeout() {
					c.bufferPool.Put(bufPtr)
					continue // 超时继续读取
				}

				errChan <- err
				return
			}

			if n == 0 {
				// 收到空数据
				c.bufferPool.Put(bufPtr)
				emptyDataCount++

				if emptyDataCount >= maxEmptyDataCount {
					// 连续收到多次空数据，通知主循环关闭连接
					select {
					case emptyDataChan <- true:
					case <-c.closeChan:
					}
					return
				}
				continue
			}

			// 重置空数据计数器
			emptyDataCount = 0

			// 创建新切片发送，保留原始缓冲区
			data := make([]byte, n)
			copy(data, buf[:n])
			c.bufferPool.Put(bufPtr) // 立即放回指针

			select {
			case readChan <- data:
			case <-c.closeChan:
				return
			}
		}
	}
}

// writeLoop 循环写入
func (c *Client) writeLoop() {
	for {
		select {
		case data := <-c.writeChan:
			_ = c.conn.SetWriteDeadline(time.Now().Add(c.server.writeTimeout))
			if _, err := c.conn.Write(data); err != nil {
				// 检查是否是连接关闭错误
				if errors.Is(err, net.ErrClosed) || errors.Is(err, io.ErrClosedPipe) ||
					errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
					c.server.logger.Info("Write failed: connection closed for client %s", c.conn.RemoteAddr())
				} else {
					c.server.logger.Error("Write error for client %s: %v", c.conn.RemoteAddr(), err)
				}
				c.Close()
				return
			}
		case <-c.closeChan:
			return
		}
	}
}

// processData 解析消息数据
func (c *Client) processData(data []byte) error {
	// 更新最后活动时间
	c.lastActive = time.Now()

	// 处理协议头
	if len(data) < protocol.NetHeadSize {
		return errors.New("incomplete header")
	}

	hbuf := data[:protocol.NetHeadSize]
	head, err := protocol.ParseNetHead(hbuf)
	if err != nil {
		return fmt.Errorf("header parse failed: %v", err)
	}

	// 处理消息体
	if len(data) < int(head.PkgLen) {
		return errors.New("incomplete body")
	}

	body := data[protocol.NetHeadSize:int(head.PkgLen)]
	return c.handleMessage(head.Type, body)
}

// handleConnection 检查接收到的信息
func (c *Client) handleMessage(headType uint8, msgData []byte) error {
	defer func() {
		if r := recover(); r != nil {
			c.server.logger.Error("Message processing panic: %v", r)
		}
	}()
	c.server.dataer.Data("proto序列化后[TCP_receive]: %v", msgData) //proto序列化后的数据
	msg := &protocol.ProtoCommMsg{}
	if err := proto.Unmarshal(msgData, msg); err != nil {
		return fmt.Errorf("deserialization failed: %v", err)
	}
	c.server.dataer.Data("proto反序列化后[TCP_receive]: %v", msg) //proto反序列化后的数据

	//检查包头协议类型，只有DCEvent或DCCmdRsp的类型才能被处理
	if msg.MsgProto != protocol.DCEvent && msg.MsgProto != protocol.DCCmdRsp {
		return fmt.Errorf("client illegal request: not in DCEvent and DCCmdRsp mode。data:%v", msg)
	}

	//检查包头协议模式，客户端只有DCSingle的模式才能被处理
	if msg.MsgProtoExt != protocol.DCSingle {
		return fmt.Errorf("do not accept client broadcasts。data:%v", msg)
	}

	//检查客户端是否，注册后才有心跳
	if !c.isRegistered && msg.MsgType != protocol.CTSRegister {
		c.server.logger.Warn("Unregistered client attempted to send message type: 0x%x", msg.MsgType)
		return fmt.Errorf("client must register first")
	}
	now := time.Now()
	nt := now.Format("15:04:05.000")
	fmt.Printf("%v 接收到的协议：0x%x\n", nt, msg.MsgType)
	c.server.logger.Info("接收到的协议：0x%x", msg.MsgType)
	// 记录机场编号（如果是注册消息）
	if msg.MsgProto == protocol.DCEvent {
		switch msg.MsgType {
		case protocol.CTSRegister:
			return c.handleRegister(headType, msg)
		case protocol.CTSHeartbeat:
			return c.handleHeartbeat(headType)
		case protocol.STCHeartbeatRsp:
			return c.handleHeartbeatRsp()
		default:
			return fmt.Errorf("unknown message type from %s: 0x%x", c.conn.RemoteAddr(), msg.MsgType)
		}
	}
	return nil
}

// handleRegister 处理注册消息
func (c *Client) handleRegister(headType uint8, msg *protocol.ProtoCommMsg) error {
	var code, uuid string
	var replyType uint8

	if headType == protocol.NetHeadTypeJSON {
		replyType = headType
		var jsonData map[string]any
		if errs := json.Unmarshal([]byte(msg.Data), &jsonData); errs != nil {
			return fmt.Errorf("parse JSON error:%v", errs)
		}

		for k, v := range jsonData {
			switch k {
			case "code":
				code = utils.FastAnyToString(v)
			case "trkn":
				uuid = utils.FastAnyToString(v)
			}
		}
	} else {
		replyType = uint8(protocol.NetHeadTypeProtobuf)
	}

	// 验证必要字段
	if code == "" || code != config.Config.AirPort {
		_ = c.CreateMsgSend(replyType, c.registeResponse(-1003), protocol.STCRegister, protocol.DCEvent, protocol.DCSingle)
		return fmt.Errorf("missing required fields from %s (code: %s)", c.conn.RemoteAddr(), code)
	}

	if uuid == "" {
		_ = c.CreateMsgSend(replyType, c.registeResponse(-1004), protocol.STCRegister, protocol.DCEvent, protocol.DCSingle)
		return fmt.Errorf("missing required fields from %s (uuid: %s)", c.conn.RemoteAddr(), uuid)
	}

	// 验证UUID格式
	if !utils.IsValidUUID(uuid) {
		_ = c.CreateMsgSend(replyType, c.registeResponse(-1002), protocol.STCRegister, protocol.DCEvent, protocol.DCSingle)
		return fmt.Errorf("invalid UUID format from %s: %s", c.conn.RemoteAddr(), uuid)
	}

	// 检查UUID是否已被使用
	if c.server.IsUUIDRegistered(uuid) {
		_ = c.CreateMsgSend(replyType, c.registeResponse(-1001), protocol.STCRegister, protocol.DCEvent, protocol.DCSingle)
		return fmt.Errorf("UUID already in use from %s: %s", c.conn.RemoteAddr(), uuid)
	}

	// 注册客户端
	c.airportNum = code
	c.uuid = uuid
	c.isValidUUID = true
	c.isRegistered = true

	// 将UUID添加到服务器注册表
	c.server.RegisterUUID(uuid, c)
	c.server.logger.Info("client registered successfully - Airport: %s, UUID: %s", code, uuid)
	return c.CreateMsgSend(replyType, c.registeResponse(0), protocol.STCRegister, protocol.DCEvent, protocol.DCSingle)
}

// handleHeartbeat 处理被动心跳
func (c *Client) handleHeartbeat(headType uint8) error {
	c.lastActive = time.Now()
	c.server.logger.Info("execute handleHeartbeat")
	return c.CreateMsgSend(headType, c.HeartbeatResponse(), protocol.STCHeartbeat, protocol.DCEvent, protocol.DCSingle)
}

// handleHeartbeatRsp 处理主动心跳的回复
func (c *Client) handleHeartbeatRsp() error {
	c.lastActive = time.Now()
	return nil
}

// activeSendHeartbeat 主动心跳
func (c *Client) activeSendHeartbeat() error {
	return c.CreateMsgSend(protocol.NetHeadTypeProtobuf, c.HeartbeatResponse(), protocol.CTSHeartbeatRsp, protocol.DCEvent, protocol.DCSingle)
}

// registeResponse 注册消息格式化返回数据
func (c *Client) registeResponse(code int) string {
	replyData := map[string]any{
		"code": code,
	}
	jsonStr, err := json.Marshal(replyData)
	if err != nil {
		c.server.logger.Error("JSON 编码错误:%v", err)
	}
	return string(jsonStr)
}

// HeartbeatResponse 客户端心跳消息格式化返回数据
func (c *Client) HeartbeatResponse() string {
	replyData := map[string]any{
		"s": time.Now().UnixMilli(),
	}
	jsonStr, err := json.Marshal(replyData)
	if err != nil {
		c.server.logger.Error("JSON 编码错误:%v", err)
	}
	return string(jsonStr)
}

// CreateMsgSend 创建返回消息,并发送
func (c *Client) CreateMsgSend(headType uint8, respData string, respType int32, respProto int32, respProtoExt int32) error {
	c.server.dataer.Data("json序列化后[TCP_send]: %v", respData)
	// 创建消息
	resp, err := protocol.ReplyMsg(headType, respData, respType, respProto, respProtoExt)
	now := time.Now()
	nt := now.Format("15:04:05.000")
	fmt.Printf("%v 发送到的协议：0x%x\n", nt, respType)
	if err != nil {
		return fmt.Errorf("protobuf marshal failed: %v", err)
	}

	return c.sendProtobufMsg(resp)
}

// sendProtobufMsg 发送protobuf数据给客户端
func (c *Client) sendProtobufMsg(resp []byte) error {
	select {
	case c.writeChan <- resp:
		return nil
	case <-c.closeChan:
		return fmt.Errorf("connection closed")
	case <-time.After(c.server.writeTimeout):
		return fmt.Errorf("write timeout")
	}
}

// Close 关闭客户端与TCP服务端连接
func (c *Client) Close() {
	c.closeOnce.Do(func() {
		close(c.closeChan)

		if c.conn != nil {
			if c.isRegistered && c.uuid != "" {
				c.server.UnregisterUUID(c.uuid)
			}

			_ = c.conn.Close()
			c.server.logger.Info("Client %s disconnected", c.conn.RemoteAddr())

			// 重置状态
			c.uuid = ""
			c.airportNum = ""
			c.isValidUUID = false
			c.isRegistered = false
		}
	})
}

// IsConnected 检查客户端是否仍然连接
func (c *Client) IsConnected() bool {
	select {
	case <-c.closeChan:
		return false
	default:
		return true
	}
}
